package edu.cicese.tm;

import com.jsurf.Points;
import com.jsurf.SurfUtil;
import com.sun.awt.AWTUtilities;

import javax.imageio.ImageIO;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingConstants;
import javax.swing.border.LineBorder;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by: Eduardo Quintana Contreras
 * Date: 16/03/11
 * Time: 04:43 PM
 */
public class DialogChanges extends JDialog implements Runnable{

	private FrameSpace frmSpace;
	public JProgressBar pbProgress;
	private JLabel lblProgress;

	public double entryPerc, entryPerc1, entryPerc2, deletePerc = 0, deletePerc1, clusterPerc = 0, clusterPerc1;
	public int clustersCreated = 0;
	private int entriesCreated = 0, entriesDeleted = 0;

	public DialogChanges(FrameSpace owner) {
		super(owner);
		this.frmSpace = owner;
		initComponents();
	}

	//! Creates the GUI components
	public void initComponents() {
		setUndecorated(true);
		setSize(220, 63);
		Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
		Rectangle window = getBounds();
		setLocation((screen.width - window.width) / 2, (screen.height - window.height) / 2);

		JPanel pProgress = new JPanel();
		pProgress.setLayout(null);
		pProgress.setBorder(new LineBorder(new Color(79, 129, 189), 2));

		JLabel lblChanges = new JLabel("", SwingConstants.CENTER);
		SwingUtil.addLabel(lblChanges, 10, 2, 200, 20, "Guardando cambios", pProgress, null);
		lblChanges.setFont(new Font("Segoe UI", Font.BOLD, 12));

		pbProgress = new JProgressBar();
		pbProgress.setBackground(Color.WHITE);
		pbProgress.setBounds(10, 24, 200, 20);
		pbProgress.setBorder(new LineBorder(Color.LIGHT_GRAY, 1));
		pbProgress.setFont(new Font("Segoe UI", Font.BOLD, 12));
		pbProgress.setStringPainted(true);
		pbProgress.setForeground(new Color(79, 129, 189));

		lblProgress = new JLabel("", SwingConstants.RIGHT);
		SwingUtil.addLabel(lblProgress, 10, 46, 200, 15, "", pProgress, null);
		lblProgress.setFont(new Font("Segoe UI", Font.PLAIN, 10));

		pProgress.add(pbProgress);
		getContentPane().add(pProgress);
	}

	public void run() {
		setVisible(true);
		frmSpace.setEnabled(false);
		AWTUtilities.setWindowOpacity(frmSpace, 0.75f);

		int newEntries = 0, entriesToDelete = 0;

		// load the space's interest-point clusters
//		ArrayList<ImageClusters> subClusters = SurfUtil.loadSubClusters(frmSpace.spaceID);
//		if (subClusters == null) {
//			subClusters = new ArrayList<ImageClusters>();
//		}

		// load the space's matching matrix
		Map<String, List<Match>> mMatrix = SurfUtil.loadMatchingMatrix(frmSpace.spaceID);
		if (mMatrix == null) {
			mMatrix = new HashMap<String, List<Match>>();
		}

		// count new entries and entries to delete
		for (Thumb thumb : frmSpace.imgThumbnails) {
			if (!thumb.isNew && thumb.toDelete) {
				entriesToDelete++;
			}
			else if (thumb.isNew && !thumb.toDelete) {
				newEntries++;
			}
		}

		// compute percentages
		if (newEntries > 0) {
			if (entriesToDelete <= 100) {
				deletePerc = Math.ceil(entriesToDelete / 10d) * 3;
			}
			else {
				deletePerc = 30;
			}
			if (newEntries > 1) {
				clusterPerc = 10d;
				clusterPerc1 = 10d / frmSpace.imgThumbnails.size();
			}
			entryPerc = (100 - deletePerc - clusterPerc) / newEntries;
			entryPerc1 = entryPerc / 6;
			entryPerc2 = entryPerc * 2 / 3;
		}
		else {
			deletePerc = 100 - clusterPerc;
		}
		deletePerc1 = deletePerc / entriesToDelete;

		// DELETE
		List<Integer> thumbIndexes = new ArrayList<Integer>();
		int i = 0;
		for (Thumb thumb : frmSpace.imgThumbnails) {
			if (!thumb.isNew) {
				// If the image entry already existed and needs to be deleted
				if (thumb.toDelete) {
					lblProgress.setText("Eliminando imágenes...");
					String imageID = thumb.imageName.substring(0, 3);
					// Delete entries from the matching matrix
					SurfUtil.deleteFromMatchingMatrix(mMatrix, /*subClusters, */imageID);
					// Save matching matrix
					Utilities.saveToFile(mMatrix, Utilities.spaceDir + frmSpace.spaceID + "\\matrix.mm");
					// Delete poi and img files
					deleteFiles(imageID);
					// Add entry to POI-Changelog
					Utilities.addToLog(frmSpace.spaceID, imageID, "POIchangelog.ans");
					thumbIndexes.add(i);
					entriesDeleted++;
					setValueDeletion();
				}
			}
			// If the image entry didn't existed and needs to be deleted
			else if (thumb.toDelete) {
				thumbIndexes.add(i);
			}
			i++;
		}
		// Remove image entries
		for (i = 0; !thumbIndexes.isEmpty(); i++) {
			frmSpace.imgThumbnails.remove(thumbIndexes.get(0) - i);
			thumbIndexes.remove(0);
		}

		// CREATE
		// If there are new entries to create
		if (newEntries > 0) {
			List<String> imageIDs = new ArrayList<String>();
			// Load the spaceID interest points
			lblProgress.setText("Cargando archivos de características...");
			SurfUtil.loadPOIs(frmSpace.spaceID);
			for (Thumb thumb : frmSpace.imgThumbnails) {
				if (thumb.isNew) {
					BufferedImage img;
					try {
						// Create the image in the corresponding resolutions
						lblProgress.setText("Generando imágenes...");
						img = ImageIO.read(new File(thumb.imagePath));
						int w, h;
						String imageID = frmSpace.getNewImageID(imageIDs), filename;
						for (String[] r : Utilities.imgResolutions) {
							w = Integer.valueOf(r[1]);
							h = Integer.valueOf(r[2]);
							filename = Utilities.getImgDir(frmSpace.spaceID) + r[0] + "\\" + imageID + ".jpg";
							ImageIO.write(frmSpace.getScaledInstance(img, w, h, true), "jpg", new File(filename));
						}

						setValue((int) Math.ceil(entryPerc1));

						// Get the interest points
						lblProgress.setText("Obteniendo características...");
						String poiFile;


						//TODO: Check the configuration, RESvsTHR
						// Save the IPs file for the location algorithm [Res=480x360, THR=0.001]
						poiFile = Utilities.getPoiDir(frmSpace.spaceID, "480x360", "001") + imageID + ".poi";
						Utilities.saveToFile(new Points(SurfUtil.getInterestPoints(
										Utilities.getImgDir(frmSpace.spaceID) + "480x360" + "\\" + imageID + ".jpg",
										0.001f), frmSpace.spaceID), poiFile);

						// save the IPs file for the tag searching algorithm [Res=800x600, THR=0.0001]
						poiFile = Utilities.getPoiDir(frmSpace.spaceID, "800x600", "0001") + imageID + ".poi";
						Utilities.saveToFile(new Points(SurfUtil.getInterestPoints(
										Utilities.getImgDir(frmSpace.spaceID) + "800x600" + "\\" + imageID + ".jpg",
										0.0001f), frmSpace.spaceID), poiFile);

						setValue((int)Math.ceil(entryPerc1 * 2));

//						for (String res : Utilities.poiResolutions) {
//							for (int t = 0; t < Utilities.thresholds.length; t++) {
//								poiFile = Utilities.getPoiDir(frmSpace.spaceID, res, Utilities.thresholds[t])
//										+ imageID + ".poi";
//								Utilities.saveToFile(new Points(SurfUtil.getInterestPoints(
//												Utilities.getImgDir(frmSpace.spaceID) + res + "\\" + imageID + ".jpg",
//												Utilities.thresholdsf[t]),
//										frmSpace.spaceID), poiFile);
//							}
//						}

						// update the matching matrix
						lblProgress.setText("Actualizando matriz de semejanza...");
						poiFile = Utilities.getPoiDir(frmSpace.spaceID) + imageID + ".poi";
						SurfUtil.addToMatchingMatrix(mMatrix, /*subClusters, */imageID, poiFile, this);

						// save matching matrix
						Utilities.saveToFile(mMatrix, Utilities.spaceDir + frmSpace.spaceID + "\\matrix.mm");

						// save sub-clusters
//						Utilities.saveToFile(subClusters, Utilities.spaceDir + frmSpace.spaceID + "\\imgClusters");

						// add entry to POI-Changelog
						Utilities.addToLog(frmSpace.spaceID, imageID, "POIchangelog.ans");

					} catch (IOException e) {
						e.printStackTrace();
					}

					entriesCreated++;
				}
			}
		}

		/*// save sub-clusters
		Utilities.saveToFile(subClusters, Utilities.spaceDir + frmSpace.spaceID + "\\imgClusters");

		// update meta-features
		lblProgress.setText("Actualizando meta-IPs...");
		Utilities.saveToFile(SurfUtil.updateMetafeatures(subClusters, this),
				Utilities.spaceDir + frmSpace.spaceID + "\\clusters");*/

		setVisible(false);
		dispose();
		frmSpace.setComponents();
		frmSpace.setEnabled(true);
		frmSpace.toFront();
		AWTUtilities.setWindowOpacity(frmSpace, 1f);
	}

	//! Deletes the img and poi files of a given entry
	@SuppressWarnings({"ResultOfMethodCallIgnored"})
	private void deleteFiles(String imageID) {
		for (String[] r : Utilities.imgResolutions) {
			new File(Utilities.getImgDir(frmSpace.spaceID) + r[0] + "\\" + imageID + ".jpg").delete();
//			filename = Utilities.getImgDir(frmSpace.spaceID) + r[0] + "\\" + imageID + ".jpg";
		}
		for (String r : Utilities.poiResolutions) {
			for (String t : Utilities.thresholds) {
//				System.out.println(Utilities.getPoiBaseDir(frmSpace.spaceID) + r + "\\" + t + "\\" + imageID + ".poi");
				new File(Utilities.getPoiBaseDir(frmSpace.spaceID) + r + "\\" + t + "\\" + imageID + ".poi").delete();
			}
		}
	}

	//! Sets the progress bar value after a deletion
	public void setValueDeletion() {
		pbProgress.setValue((int)Math.ceil(deletePerc1 * entriesDeleted));
	}

	//! Sets the progress bar value after an addition
	public void setValue(int value){
//		System.out.println("DELETED + CREATED: " + (int)deletePerc + (int)Math.ceil(entryPerc * entriesCreated));
//		System.out.println("CLUSTERS CREATED: " + (int)Math.ceil(clusterPerc1 * clustersCreated));
//		System.out.println("VALUE: " + value);
		pbProgress.setValue((int)deletePerc +
				(int)Math.ceil(entryPerc * entriesCreated) +
				(int)Math.ceil(clusterPerc1 * clustersCreated) +
				value);
	}
}
